﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

using SouthApps.MobileHealth.SDK.DAL.Model;
using SouthApps.MobileTasks.SDK.DAL.Repositories;
using SouthApps.Framework.LoggerService;

namespace SouthApps.MobileHealth.SDK.Cache
{
    public static class CentrosAtencionCache
    {
        private static ReaderWriterLock cacheReaderWriterLock = new ReaderWriterLock();
        private static IFinanciadoresRepository financiadoresRepository;
        private static Dictionary<int, List<CentroAtencion>> centrosAtencion = new Dictionary<int, List<CentroAtencion>>();
        private static bool initialized = false;
        private static object lockObject = new object();

        public static void Initialize(List<int> financiadoresId)
        {
            try
            {
                lock (lockObject)
                {
                    if (!initialized)
                    {
                        CentrosAtencionCache.financiadoresRepository = new FinanciadoresRepository();
                        CentrosAtencionCache.LoadCentrosAtencionFromDatabase(financiadoresId);
                        initialized = true;
                    }
                }
            }
            catch (Exception ex)
            {
                LoggerService.Log(LogLevel.Error, "An error ocurred while initializing centros de atencion cache.", ex);
                throw ex;
            }
        }

        private static void LoadCentrosAtencionFromDatabase(List<int> financiadoresId)
        {
            cacheReaderWriterLock.AcquireWriterLock(Timeout.Infinite);

            try
            {
                foreach (int financiadorId in financiadoresId)
                {
                    List<CentroAtencion> centroAtencion = CentrosAtencionCache.financiadoresRepository.GetCentrosAtencionFinanciador(financiadorId);
                    CentrosAtencionCache.centrosAtencion.Add(financiadorId, centroAtencion);
                }
            }
            finally
            {
                cacheReaderWriterLock.ReleaseWriterLock();
            }
        }

        public static void AddCentroAtencionToCache(int financiadorId, CentroAtencion centroAtencion)
        {
            cacheReaderWriterLock.AcquireReaderLock(Timeout.Infinite);

            if (CentrosAtencionCache.centrosAtencion.ContainsKey(financiadorId))
            {
                List<CentroAtencion> sucursalesPrestadorList = CentrosAtencionCache.centrosAtencion[financiadorId];

                cacheReaderWriterLock.UpgradeToWriterLock(Timeout.Infinite);
                sucursalesPrestadorList.Add(centroAtencion);
                CentrosAtencionCache.centrosAtencion[financiadorId] = sucursalesPrestadorList;

                cacheReaderWriterLock.ReleaseLock();
            }
            else
            {
                List<CentroAtencion> sucursalesPrestadorList = new List<CentroAtencion>();
                sucursalesPrestadorList.Add(centroAtencion);

                cacheReaderWriterLock.UpgradeToWriterLock(Timeout.Infinite);
                CentrosAtencionCache.centrosAtencion.Add(financiadorId, sucursalesPrestadorList);

                cacheReaderWriterLock.ReleaseLock();
            }
        }

        public static void RemoveCentroAtencionFromCache(int financiadorId, CentroAtencion sucursalPrestador)
        {
            cacheReaderWriterLock.AcquireReaderLock(Timeout.Infinite);

            if (!CentrosAtencionCache.centrosAtencion.ContainsKey(financiadorId))
                return;

            List<CentroAtencion> sucursalesPrestadorList = CentrosAtencionCache.centrosAtencion[financiadorId];

            cacheReaderWriterLock.UpgradeToWriterLock(Timeout.Infinite);
            sucursalesPrestadorList.Remove(sucursalPrestador);
            CentrosAtencionCache.centrosAtencion[financiadorId] = sucursalesPrestadorList;

            cacheReaderWriterLock.ReleaseLock();
        }

        public static void UpdateCentroAtencionToCache(int financiadorId, CentroAtencion centroAtencion)
        {
            cacheReaderWriterLock.AcquireReaderLock(Timeout.Infinite);

            if (!CentrosAtencionCache.centrosAtencion.ContainsKey(financiadorId))
                return;

            List<CentroAtencion> sucursalesPrestadorList = CentrosAtencionCache.centrosAtencion[financiadorId];
            //TODO: terminar
        }

        public static List<CentroAtencion> GetCentrosAtencion(int financiadorId)
        {
            return CentrosAtencionCache.GetCentrosAtencion(financiadorId, null);
        }

        public static List<CentroAtencion> GetCentrosAtencion(int financiadorId, int? departamentoId)
        {
            cacheReaderWriterLock.AcquireReaderLock(Timeout.Infinite);

            try
            {
                if (!CentrosAtencionCache.centrosAtencion.ContainsKey(financiadorId))
                    return new List<CentroAtencion>();

                var locacionesServicioEspecial = from centroAtencion in CentrosAtencionCache.centrosAtencion[financiadorId]
                                                 where (departamentoId == null || centroAtencion.departamentoId == departamentoId)
                                                 select centroAtencion;


                return locacionesServicioEspecial.ToList();
            }
            finally
            {
                cacheReaderWriterLock.ReleaseReaderLock();
            }
        }
    }
}
